/*
 * 
 * Copyright 2010 David H Pollack
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 * 
 * 
 */

package com.dhpollack.rotogss.servlets;

import java.io.IOException;
import java.io.StringReader;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.regex.Pattern;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;

import net.sf.jsr107cache.Cache;
import net.sf.jsr107cache.CacheException;
import net.sf.jsr107cache.CacheManager;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.dhpollack.rotogss.data.RotoGSSLeagueXml;
import com.dhpollack.rotogss.data.YahooGames;
import com.dhpollack.rotogss.data.YahooLeagueTeamStandings;
import com.dhpollack.rotogss.data.YahooLeagueTeams;
import com.dhpollack.rotogss.data.YahooLeagues;
import com.dhpollack.rotogss.helper.PMF;
import com.dhpollack.rotogss.helper.XPATH;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

/**
 * @author davidpl
 *
 */
public class YStoreLeagueTeamsServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = -3805575709133741294L;

	private String league;
	
	private Integer game;
	
	private static XPath xPath = XPATH.get().newXPath();
	
	protected void service(HttpServletRequest req, HttpServletResponse resp) 
    throws ServletException, IOException {
		
		league = req.getParameter("league");
		
		if(league == null) {
			log("No league set");
			return;
		} else {
			log("Processing stats for " + league);
		}
		
		// Processing for game key.  Will be replaced with game parse
		String regex = "\\.";
		Pattern numSplit = Pattern.compile(regex);
		String[] m = numSplit.split(league);
		game = Integer.parseInt(m[0]);
		
		RotoGSSLeagueXml xml = getLeagueXmlFromApp();
		
		//Date league_update = xml.getUpdateTimestamp();
		String league_xml = xml.getLeagueXml();
		NodeList team_nodes = parseLeagueXml(league_xml, "league/standings/teams/team");
		int team_count = team_nodes.getLength();
		for(int i=0;i<team_count;i++) {
			try {
				Key team_key = saveTeamToDatastore(team_nodes.item(i), false);
				req.setAttribute(team_key.getName(), team_key);
			} catch (XPathExpressionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	private RotoGSSLeagueXml getLeagueXmlFromApp() {
        Cache cache = null;

        try {
            cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
        } catch (CacheException e) {
            // ...
        	log("Memcache creation failed");
        }
        
        String memcache_key = league + "-xml";
        RotoGSSLeagueXml xml = null;
        
        if(cache != null && cache.containsKey(memcache_key)) {
        	log("Using Memcache");
        	xml = (RotoGSSLeagueXml) cache.get(memcache_key);
        }
        if(xml == null) {
        	log("Using Datastore");
            PersistenceManager pm = PMF.get().getPersistenceManager();
            Key key = new KeyFactory.Builder(RotoGSSLeagueXml.class.getSimpleName(), league).getKey();
            try {
            	xml = pm.getObjectById(RotoGSSLeagueXml.class, key);
            } catch(JDOObjectNotFoundException e) {
            	log("LeagueXml not found in datastore");
            	e.printStackTrace();
            }
        }
		return xml;
	}

	private NodeList parseLeagueXml(String leagues_xml, String expression) {
		NodeList n = null;
		try {
			InputSource is = new InputSource(new StringReader(leagues_xml));
			Document response = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
			n = (NodeList)xPath.evaluate( expression , response, XPathConstants.NODESET);
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (XPathExpressionException e) {
			e.printStackTrace();
		}
		return n;
	}
	
	private Key saveTeamToDatastore(Node node, boolean force_update)
	throws XPathExpressionException {
		// TODO Auto-generated method stub
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		String team_key = (String)xPath.evaluate("team_key", node, XPathConstants.STRING);
		Key key = new KeyFactory.Builder(YahooGames.class.getSimpleName(), game)
								.addChild(YahooLeagues.class.getSimpleName(), league)
								.addChild(YahooLeagueTeams.class.getSimpleName(), team_key)
								.getKey();
		YahooLeagueTeams ylt;
		try {
			tx.begin();
			try {
				ylt = pm.getObjectById(YahooLeagueTeams.class, key);
				log("League Already Found Overwriting Datastore " + force_update);
			} catch(JDOObjectNotFoundException e) {
				log("Creating new YahooLeagueTeams entity for " + key.getName());
				ylt = new YahooLeagueTeams();
				ylt.setTeamKey(key);
				ylt.setGoogleUsers(new LinkedHashSet<Key>());
				ylt.setLeagueTeamStandings(new LinkedHashSet<YahooLeagueTeamStandings>());
				
				force_update = true;
			}
			if(force_update) {
				
				Integer team_id = Integer.parseInt((String)xPath.evaluate("team_id", node, XPathConstants.STRING));
				String team_name = (String)xPath.evaluate("name", node, XPathConstants.STRING);
				String team_url = (String)xPath.evaluate("url", node, XPathConstants.STRING);
				
				ylt.setTeamId(team_id);
				ylt.setName(team_name);
				ylt.setUrl(team_url);
				
				NodeList managerNodes = (NodeList)xPath.evaluate("managers/manager", node, XPathConstants.NODESET);
				int nodeManagerCount = managerNodes.getLength();
				for (int i = 0; i < nodeManagerCount; i++) {
					  
					Integer manager_id = Integer.parseInt((String)xPath.evaluate("manager_id", managerNodes.item(i), XPathConstants.STRING));
					String manager_name = (String)xPath.evaluate("nickname", managerNodes.item(i), XPathConstants.STRING);
					
					try {
						String is_comanager  = (String) xPath.evaluate("is_comanager", managerNodes.item(i), XPathConstants.STRING);
						log("ManagerId: " + manager_id + "\nManagerName: " + manager_name);
						if(is_comanager.equals("1")) {
							log("Found Comanager");
							ylt.setComanagerId(manager_id);
							ylt.setComanagerName(manager_name);
						} else {
							ylt.setManagerId(manager_id);
							ylt.setManagerName(manager_name);
						}
					} catch(XPathExpressionException e) {
						log("XPathException Caught for Manager");
					}
					  
				}
				pm.makePersistent(ylt);
			}
			tx.commit();
		} finally {
			if(tx.isActive()) {
				tx.rollback();
			}
		}
		return key;
	}



}
